import java.math.BigDecimal;
import java.util.Vector;

/**
 * Does many of the things an actual bank does.
 * 
 * Has 3 Vectors that manage CheckingAccounts,
 * SavingAccounts and CreditCards.
 * 
 * @author svenb
 *
 */

public class Bank 
{
	public String name;
	public Vector<CreditCard> creditCards;
	public Vector<CheckingAccount> checkingAccounts;
	public Vector<SavingsAccount> savingAccounts;
	
	public Bank(String name)
	{
		this.name = name;
		checkingAccounts = new Vector<CheckingAccount>();
		savingAccounts = new Vector<SavingsAccount>();
		creditCards = new Vector<CreditCard>();
	}
	
	/**
	 * All the open... methods create a new instance of the type,
	 * add it to the Vector and return the account number.
	 * 
	 * @param newCustomer
	 * @return
	 */
	public int openCheckingAccount(Customer newCustomer)
	{
		CheckingAccount newAccount = new CheckingAccount(newCustomer);
		checkingAccounts.add(newAccount);
		return newAccount.getAccountNumber();
	}
	
	public int openSavingsAccount(Customer newCustomer)
	{
		SavingsAccount newAccount = new SavingsAccount(newCustomer);
		savingAccounts.add(newAccount);
		return newAccount.getAccountNumber();
	}
	
	/**
	 * openCreditCard needs both Customer and an existing
	 * CheckingAccount. Really it should only need a CheckingAccount
	 * since that has a Customer in it already. This is an entry-way for trouble.
	 * 
	 * Also it returns -1 if the customer doesn't pass the credit check, which
	 * can be trouble if it's interpreted as an account number.
	 * 
	 * @param newCustomer
	 * @param appCheck
	 * @return
	 */
	public int openCreditCard(Customer newCustomer, CheckingAccount appCheck){
		if(qualifyForCreditCard(newCustomer, appCheck)){
			if((appCheck.getBalance().compareTo(new BigDecimal("2500")) == -1) || (appCheck.getBalance().compareTo(new BigDecimal("2500")) == 0))
			{
				CreditCard newCard = new CreditCard(newCustomer, new BigDecimal("2500"));
				creditCards.add(newCard);
				return newCard.getAccountNumber();
			}
			else
			{
				CreditCard newCard = new CreditCard(newCustomer, new BigDecimal("5000"));
				creditCards.add(newCard);
				return newCard.getAccountNumber();
			}
		}
		return -1;
	}
	
	/**
	 * This just checks for a non-negative balance in the checking account.
	 * Like openCreditCard, it could work with just a CheckingAccount.
	 * In fact, it doesn't appear to access the Customer at all.
	 * Oversight.
	 * 
	 * @param ccApplicant
	 * @param appCheck
	 * @return
	 */
	public boolean qualifyForCreditCard(Customer ccApplicant, CheckingAccount appCheck)
	{
		if(appCheck.getBalance().compareTo(new BigDecimal(0)) == -1)
		{
			return false;
		}
		else{
			return true;
		}
	}

	/**
	 * DebitCards are special because they have a CheckingAccount inside them
	 * and can't take deposits. They aren't very complicated either, so it might
	 * be more trouble to shoe-horn it in to Account inheritance and maintain it
	 * down the road than to maintain it as a separate entity. 
	 * 
	 * @param bankCust
	 * @param custCheckAcct
	 * @return
	 */
	public boolean addDebitCard(Customer bankCust, CheckingAccount custCheckAcct){
		DebitCard newCard = new DebitCard(bankCust, custCheckAcct);
		custCheckAcct.setDebitCard(newCard);
		return true;
	}
	
	/**
	 * All the withdraw... and deposit... methods 
	 * use an account number to find the index
	 * of the account in the appropriate Vector, 
	 * the return the result of 
	 * the withdrawal, True or False.
	 * 
	 * No withdrawals from Credit.
	 * 
	 * @param accountNumber
	 * @param amount
	 * @return
	 */	
	public boolean withdrawFromChecking(int accountNumber, BigDecimal amount)
	{
		CheckingAccount account = new CheckingAccount(accountNumber);
		int index = checkingAccounts.indexOf(account);
		return checkingAccounts.elementAt(index).withdrawal(amount);
	}
	
	public boolean withdrawFromSavings(int accountNumber, BigDecimal amount)
	{
		SavingsAccount account = new SavingsAccount(accountNumber);
		int index = savingAccounts.indexOf(account);
		return savingAccounts.elementAt(index).withdrawal(amount);
	}
	
	public boolean depositToChecking(int accountNumber, BigDecimal amount)
	{
		CheckingAccount account = new CheckingAccount(accountNumber);
		int index = checkingAccounts.indexOf(account);
		return checkingAccounts.elementAt(index).deposit(amount);
	}
	
	public boolean depositToSavings(int accountNumber, BigDecimal amount)
	{
		SavingsAccount account = new SavingsAccount(accountNumber);
		int index = savingAccounts.indexOf(account);
		return savingAccounts.elementAt(index).deposit(amount);
	}
	
	public boolean depositToCredit(int accountNumber, BigDecimal amount)
	{
		SavingsAccount account = new SavingsAccount(accountNumber);
		int index = creditCards.indexOf(account);
		return creditCards.elementAt(index).deposit(amount);
	}

	/**
	 * This is a poorly-named method that opens one of each kind
	 * of account for the Customer. It doesn't do anything with the 
	 * result of openCreditCard, and probably should.
	 * 
	 * @param newCustomer
	 * @return
	 */
	public int openFullPackage(Customer newCustomer)
	{
		CheckingAccount newAccount = new CheckingAccount(newCustomer);
		checkingAccounts.add(newAccount);
		openCreditCard(newCustomer, newAccount);
		SavingsAccount newSavingsAccount = new SavingsAccount(newCustomer);
		savingAccounts.add(newSavingsAccount);
		new DebitCard(newCustomer, newAccount);
		return newAccount.getAccountNumber();
	}
}
